﻿using Aspose.Words;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

namespace Archives
{
    #region 压缩文件及文件夹
    /// <summary>
    /// 压缩文件及文件夹
    /// </summary>
    public class CompressFileZip
    {
        private ZipOutputStream zos = null;
        private string strBaseDir = "";

        #region 创建临时文件夹
        /// <summary>
        /// 创建临时文件夹
        /// </summary>
        /// <param name="name">文件夹名称</param>
        /// <param name="path">文件夹所在路径</param>
        /// <returns></returns>
        public string CreateTempFolder(string name, string path,string messageTitle)
        {
            //遍历服务器指定文件夹下的所有文件
            var serverPath = Directory.GetDirectories(path);
            var namePath = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString()
                         + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString();
            string tempFolder = Path.Combine(path, name);
            if (string.IsNullOrWhiteSpace(name))
            {
                tempFolder = Path.Combine(tempFolder, messageTitle + "_" + namePath);
            }
            if (Directory.Exists(tempFolder))
            {
                Random rd = new Random();
                tempFolder = tempFolder + "_" + namePath;
            }
            Directory.CreateDirectory(tempFolder); //创建临时文件夹
            return tempFolder + "\\";
        }
        #endregion

        #region 添加文件到压缩文件中
        /// <summary>
        /// 添加文件到压缩文件中
        /// </summary>
        /// <param name="PathStr">路径</param>
        public void addZipEntry(string PathStr)
        {
            DirectoryInfo di = new DirectoryInfo(PathStr);
            foreach (DirectoryInfo item in di.GetDirectories())
            {
                addZipEntry(item.FullName);
            }
            foreach (FileInfo item in di.GetFiles())
            {
                FileStream fs = System.IO.File.OpenRead(item.FullName);
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                string strEntryName = item.FullName.Replace(strBaseDir, "");
                ZipEntry entry = new ZipEntry(strEntryName);
                zos.PutNextEntry(entry);
                zos.Write(buffer, 0, buffer.Length);
                fs.Close();
            }
        }
        #endregion

        #region 输出下载压缩包
        /// <summary>
        /// 输出下载压缩包
        /// </summary>
        /// <param name="response">页面响应</param>
        /// <param name="strPath">文件所在的路径</param>
        /// <param name="strFileName">压缩文件名</param>
        /// <param name="strExt">压缩文件的扩展名</param>
        public void dlZipDir(HttpResponseBase response, string strPath, string strFileName, string strExt = null)
        {
            if (string.IsNullOrEmpty(strExt))
                strExt = ".zip"; //默认压缩文件扩展名
            MemoryStream ms = null;
            response.ContentType = "application/octet-stream";
            strFileName = HttpUtility.UrlEncode(strFileName).Replace('+', ' ');
            response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName + strExt);
            ms = new MemoryStream();
            zos = new ZipOutputStream(ms);
            strBaseDir = strPath + "\\";
            addZipEntry(strBaseDir);
            zos.Finish();
            zos.Close();
            response.Clear();
            response.BinaryWrite(ms.ToArray());
            //删除临时目录下的所有文件
            DeleteTempFiles(strPath);
            response.End();
        }
        #endregion

        #region 保存文件到临时文件夹中
        /// <summary>
        /// 保存文件到临时文件夹中
        /// </summary>
        /// <param name="content">将流内容写入字节组</param>
        /// <param name="SaveName">保存的文件名</param>
        /// /// <param name="dirPath">保存路径</param>
        /// <param name="fileExtend">保存的文件扩展名</param>
        /// <returns></returns>
        public void SaveFile(byte[] content, string SaveName, string dirPath, string fileExtend = null)
        {

            if (string.IsNullOrEmpty(fileExtend))
                fileExtend = ".doc"; //文件扩展名默认是word文档
            try
            {
                DateTime dt = DateTime.Now;
                //设置文件夹路径
                //directory = CreateTempFolder(strName, strCode);
                //文件保存完整路径
                string path = dirPath + SaveName + fileExtend;
                //验证文件夹是否存在   不存在则创建
                if (!Directory.Exists(dirPath))
                {
                    Directory.CreateDirectory(dirPath);
                }
                //以创建文件的方式写入内容
                FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write);
                BinaryWriter w = new BinaryWriter(fs);
                w.Write(content);
                w.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                throw new System.IO.FileNotFoundException("目录:" + dirPath + "没有找到!");
            }
        }
        #endregion

        #region 删除临时目录下的所有文件
        /// <summary>
        /// 删除临时目录下的所有文件
        /// </summary>
        /// <param name="tempPath">临时目录路径</param>
        private void DeleteTempFiles(string tempPath)
        {
            DirectoryInfo directory = new DirectoryInfo(tempPath);
            try
            {
                foreach (var file in directory.GetFiles())
                {
                    if (file.Attributes.ToString().IndexOf("ReadOnly") != -1)
                    {
                        file.Attributes = FileAttributes.Normal;
                    }
                    System.IO.File.Delete(file.FullName);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
        #endregion

        //#region 获取指定文件夹下的所有文件
        ///// <summary>
        ///// 获取指定文件夹下的所有文件
        ///// </summary>
        ///// <param name="Folder">文件夹名称</param>
        ///// <param name="strName">文件夹下所包含指定文件名的文件</param>
        ///// <returns></returns>
        //public List<string> GetFileList(string Folder, string strName = null)
        //{
        //    List<string> lsFile = new List<string>();
        //    if (!string.IsNullOrEmpty(Folder))
        //    {
        //        Folder = WordFilePath.GetFilePath("UploadFile", Folder + "\\");
        //        DirectoryInfo di = new DirectoryInfo(Folder);
        //        foreach (FileInfo item in di.GetFiles())
        //        {
        //            if (!string.IsNullOrEmpty(strName))
        //            {
        //                if (item.FullName.Contains(strName))
        //                    lsFile.Add(item.FullName);
        //            }
        //            else
        //                lsFile.Add(item.FullName);
        //        }
        //    }
        //    return lsFile;
        //}
        //#endregion

    }
    #endregion 

    #region 插入文档
    public class InsertFile
    {
        #region 在书签位置插入另一个文档的内容
        /// <summary>
        /// 使用DocumentBuilder对象插入一些文档对象，如插入书签，插入文本框，插入复选框
        /// 插入一个段落，插入空白页，追加或另一个word文件的内容等。
        /// </summary>
        /// <param name="doc">载入模板</param>
        /// <param name="tempFile"></param>
        /// <param name="mark">载入模版名称</param>
        /// <param name="lsFile"></param>
        public static void InsertDoc(Document doc, string mark, List<string> lsFile, string SaveName = null)
        {
            string savePath = "";
            var builder = new DocumentBuilder(doc);
            if (!string.IsNullOrEmpty(SaveName))
                SaveName = SaveName.Substring(0, SaveName.LastIndexOf("_"));
            Document doc1;
            for (int i = 0; i < lsFile.Count; i++)
            {
                if (i == 0)
                    savePath = lsFile[i].Substring(0, lsFile[i].LastIndexOf('\\') + 1);
                doc1 = new Document(lsFile[i]);//新文档
                var bookmark = doc.Range.Bookmarks[mark];
                //清空书签的文本
                //bookmark.Text = "";
                //定位到指定位置进行插入操作
                builder.MoveToBookmark(mark, false, false);
                InsertDocument(bookmark.BookmarkStart.ParentNode, doc1);
                //doc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;
                //doc1.AppendDocument(doc, ImportFormatMode.KeepSourceFormatting);

                System.IO.File.Delete(lsFile[i]); //删除已经插入的文件                
            }
            if (!string.IsNullOrEmpty(SaveName))
                doc.Save(savePath + SaveName + ".doc");
        }
        #endregion

        #region 插入文档
        /// <summary>
        /// 插入文档
        /// </summary>
        /// <param name="insertAfterNode">节点在目标文件中的内容后插入。这个节点应该是一个块级节点（段落或表格）。</param>
        /// <param name="srcDoc">插入文档</param>
        private static void InsertDocument(Node insertAfterNode, Document srcDoc)
        {
            // 确保插入点是一个段落或表格。
            if ((!insertAfterNode.NodeType.Equals(NodeType.Paragraph)) &
              (!insertAfterNode.NodeType.Equals(NodeType.Table)))
                throw new ArgumentException("插入的目的节点应该是一个段落或表格。");

            // 插入到目标段落
            CompositeNode dstStory = insertAfterNode.ParentNode;
            NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.Document, ImportFormatMode.KeepSourceFormatting);

            //在源文件中循环
            foreach (Section srcSection in srcDoc.Sections)
            {
                foreach (Node srcNode in srcSection.Body)
                {
                    // 跳过空节点
                    if (srcNode.NodeType.Equals(NodeType.Paragraph))
                    {
                        Paragraph para = (Paragraph)srcNode;
                        if (para.IsEndOfSection && !para.HasChildNodes)
                            continue;
                    }
                    // 插入到目标文档
                    Node newNode = importer.ImportNode(srcNode, true);
                    // 参考节点后插入新节点
                    dstStory.InsertAfter(newNode, insertAfterNode);
                    insertAfterNode = newNode;
                }
            }
        }
        #endregion
    }
    #endregion

    public class ZipHelper
    {
        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="sourceFilePath"></param>
        /// <param name="destinationZipFilePath"></param>
        public static void CreateZip(string sourceFilePath, string destinationZipFilePath)
        {
            if (sourceFilePath[sourceFilePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
                sourceFilePath += System.IO.Path.DirectorySeparatorChar;

            ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationZipFilePath));
            zipStream.SetLevel(6);  // 压缩级别 0-9
            CreateZipFiles(sourceFilePath, zipStream, sourceFilePath);

            zipStream.Finish();
            zipStream.Close();
        }

        /// <summary>
        /// 递归压缩文件
        /// </summary>
        /// <param name="sourceFilePath">待压缩的文件或文件夹路径</param>
        /// <param name="zipStream">打包结果的zip文件路径（类似 D:\WorkSpace\a.zip）,全路径包括文件名和.zip扩展名</param>
        /// <param name="staticFile"></param>
        private static void CreateZipFiles(string sourceFilePath, ZipOutputStream zipStream, string staticFile)
        {
            Crc32 crc = new Crc32();
            string[] filesArray = Directory.GetFileSystemEntries(sourceFilePath);
            foreach (string file in filesArray)
            {
                if (Directory.Exists(file))                     //如果当前是文件夹，递归
                {
                    CreateZipFiles(file, zipStream, staticFile);
                }

                else                                            //如果是文件，开始压缩
                {
                    FileStream fileStream = File.OpenRead(file);

                    byte[] buffer = new byte[fileStream.Length];
                    fileStream.Read(buffer, 0, buffer.Length);
                    string tempFile = file.Substring(staticFile.LastIndexOf("\\") + 1);
                    ZipEntry entry = new ZipEntry(tempFile);

                    entry.DateTime = DateTime.Now;
                    entry.Size = fileStream.Length;
                    fileStream.Close();
                    crc.Reset();
                    crc.Update(buffer);
                    entry.Crc = crc.Value;
                    zipStream.PutNextEntry(entry);

                    zipStream.Write(buffer, 0, buffer.Length);
                }
            }
        }
    }
}